#!/bin/bash
#####
# Git Customization Changle Log Output
#####

# clog命令传入的version参数
_CURRENT_TAG=""
# clog命令传入的output参数
_OUTPUT=""

#  远程仓库地址变量
REMOTE_URL=""
# 项目已有tag数组，如果存在，则以git tag输出的倒序存在
# 数组中的值为<commit_id_sha1>|<project-version>
declare -a TAGS
# 当前tag信息(<index> <commit_id_sha1> <project-version> <version>)
declare -a CURRENT_TAG
# 上一个tag信息(<index> <commit_id_sha1> <project-version> <version>)
declare -a BEFORE_TAG
# 当前命令执行的所有代码作者信息 (author <author_email> (commit_count))
# 例如：Tony Deng <wolf.deng@gmail.com> (1)
declare -a AUTHORS

VERSION_PARAMETERS=''

####
# changelog main方法
####
function main() {
    verify_version
    get_all_tag
    verify_param "$@"
    get_remote_url
    all_log
}
#####
# 验证当前git的版本是否大于2.1
#####
function verify_version() {
    version=(`git --version|awk -F ' ' '{print $3}'|cut -d '.' -f1 -f2`)
    t=`expr "$version" \>= '2.1'`
    if [[ "$t" -eq "0" ]]; then
        echo "The current Git version is less than 2.1, please upgrade to Git - 2.1 above"
        exit 1
    fi
}
#####
# 验证命令参数
#####
function verify_param() {
    PARAM=("$@")
    i=0
    for p in "${PARAM[@]}"; do
        case $p in
            "-v"|"--vesion" )
                if [[ -n "${PARAM[$i+1]}" ]]; then
                    _CURRENT_TAG=${PARAM[$i+1]}
                    # set_tag "${PARAM[$i+1]}"
                fi
                ;;
            "-o"|"--output" )
                if [[ -n "${PARAM[$i+1]}" ]]; then
                    _OUTPUT="${PARAM[$i+1]}"
                fi
                ;;
        esac
        let i++
    done
}

#####
# 获取远程仓库地址
#####
function get_remote_url() {
    if [[ -n "$1" ]]; then
        ORIGIN="$1"
    else
        ORIGIN=`git remote get-url origin`
    fi
    if [[ "$ORIGIN" == "https"* ]]; then
        REMOTE_URL="${ORIGIN%.*}"
    else
        REMOTE_URL=(`echo "$ORIGIN"|awk -F '[@:]' '{print "https://"$2"/"$3}'`)
        REMOTE_URL=("${REMOTE_URL%.*}")
    fi
}
#####
# 数组倒序排列
#####
function _array_sort_desc() {
    arr=($@)
    for (( i=0, j=${#arr[*]} ; j>=0;i++,j-- )); do
        newarray[$i]=${arr[$j]};
    done;
    echo "${newarray[*]}"
}
#####
# 获取当前所有tag
#####
function get_all_tag() {
    i=0
    # git tag -l --sort="version:refname"
    for tag in  `git for-each-ref --sort="version:refname" --format='%(objectname)|%(refname:short)' refs/tags/`; do
        tags[$i]="$tag"
        let i++
    done
    TAGS=(`_array_sort_desc "${tags[*]}"`)
    unset tags
    unset i
    unset tag
}
#####
# 获取某个tag信息
#####
function get_tag() {
    _t="$1"
    # 判断输入的版本信息是否包含项目名
    # if [[ $(echo "$1"|grep "-") != "" ]]; then
    if [[ "$1" == *"-"* ]]; then
        # _t=`echo $1|awk -F '-' '{print $2}'`
        _t=${_t##*-}
    fi
    for (( i=0; i<${#TAGS[*]};i++)); do
        # echo "$_t ${TAGS[$i]} ${TAGS[$i]##*-}"
        # if [[ "$_t" == "`echo ${TAGS[$i]}|awk -F '[|-]' '{print $3}'`" ]]; then
        if [[ "$_t" == "${TAGS[$i]##*-}" ]]; then
            tag[0]="$i"
            tag[1]="${TAGS[$i]%|*}" # tag commit_id_sha1
            tag[2]="${TAGS[$i]#*|}" # tag project_version
            tag[3]="${TAGS[$i]##*-}" # tag version
            # tag[1]=`echo ${TAGS[$i]}|awk -F '|' '{print $1}'`
            # tag[2]=`echo ${TAGS[$i]}|awk -F '|' '{print $2}'`
            # tag[3]=`echo ${TAGS[$i]}|awk -F '[|-]' '{print $3}'`
        fi
    done
    echo "${tag[*]}"
}

####
# 设置TAG相关的全局变量
####
function set_tag() {
    # for (( i = 0; i < ${#TAGS[@]}; i++ )); do
    #     echo ${TAGS[$i]}
    # done
    # get_tag "$1"
    CURRENT_TAG=(`get_tag "$1"`)
    _index="${CURRENT_TAG[0]}"
    let _index++
    if [[ $_index < ${#TAGS[*]} ]]; then
        BEFORE_TAG=(`get_tag ${TAGS[$_index]}`)
        VERSION_PARAMETERS="${BEFORE_TAG[1]}..${CURRENT_TAG[1]}"
    else
        VERSION_PARAMETERS="${CURRENT_TAG[1]}"
        unset BEFORE_TAG
    fi
}
#####
# 获得所有提交者
#####
function get_all_author() {
    # git shortlog -s -n -e --no-merges 85e76af9..3637d2b8
    _index=0
    while read _line; do
        AUTHORS[$_index]="`get_author "$_line"`"
        let _index++
    done<<EOF
`git shortlog -s -n -e --no-merges $VERSION_PARAMETERS`
EOF
}
###
# 将“751	Tony Deng <wolf.deng@gmail.com>” 这样的格式改成 "Tony Deng <wolf.deng@gmail.com> (751)"
###
function get_author() {
    echo "$1"|awk '{for(i=2;i<=NF;i++)printf $i""FS;print "("$1")"}'
}
###
# 输出所有日志
###
function all_log() {
    if [[ -n "$_CURRENT_TAG" ]]; then
        set_tag "$_CURRENT_TAG"
        simple_log
    else
        for tag in "${TAGS[@]}"; do
            set_tag "$tag"
            simple_log
        done
    fi

}
#####
# 直接输出日志到在终端
#####
function simple_log() {
    get_all_author
    if [[ -n "$_OUTPUT" ]]; then
        echo "# ${CURRENT_TAG[2]}" >> "$_OUTPUT"
        echo "" >> "$_OUTPUT"
        echo "" >> "$_OUTPUT"
    else
        echo "# ${CURRENT_TAG[2]}"
        echo ""
        echo ""
    fi

    for a in "${AUTHORS[@]}"; do
        _author=`echo "$a"|awk -F '[<\>]' '{print $2}'`
        _author_output=`echo "$a"|awk -F '[<\>]' '{print "["$1"]("$2")"$3}'`
        _cmd="git log --author='${_author}' --no-merges $VERSION_PARAMETERS --pretty=format:'* %s (%ad) [view commit %h](${REMOTE_URL[*]}/commit/%h)  ' --date=format:'%Y-%m-%d %H:%M:%S'"
        if [[ -n "$_OUTPUT" ]]; then
            echo "#### $_author_output" >> "$_OUTPUT"
            echo "" >> "$_OUTPUT"
            _cmd="$_cmd >> $_OUTPUT"
            # echo $"$_cmd"
            eval "$_cmd"
            echo "" >> "$_OUTPUT"
            echo "" >> "$_OUTPUT"
        else
            echo "#### $_author_output"
            echo ""
            # echo $"$_cmd"
            eval "$_cmd"
            echo ""
            echo ""
        fi
        unset _author
        unset _cmd
    done
    unset AUTHORS
}
#####
# 使用帮助
#####
function help() {
cat <<  EOF
GIT-CLOG(1)

NAME
       git-clog - Git Change Logs Output

SYNOPSIS
       git clog [<options>] [<revision range>] [[--] <path>...]

DESCRIPTION
       Summarizes git log output in a format suitable for inclusion in release announcements. Each commit will be grouped by author and title.

OPTIONS
       -o, --output
           The changelog output to a file.
       -v, --version
           Specify the output one version.
       -h, --help
           Prints the synopsis and a list of the most commonly used commands.
EOF
}
case $1 in
    "-h" | "--help")
        help
        ;;
    * )
        main "$@"
        exit
        ;;
esac
